package com.to8to.scene.server;

import static com.to8to.thrift.diary.behavior.ListBehaviorRequest._Fields.BHV_TYPE;
import static com.to8to.thrift.diary.behavior.ListBehaviorRequest._Fields.STATUS;
import static com.to8to.thrift.diary.behavior.ListBehaviorRequest._Fields.TGT_ID;
import static com.to8to.thrift.diary.behavior.ListBehaviorRequest._Fields.TGT_TYPE;
import static com.to8to.thrift.diary.behavior.ListBehaviorRequest._Fields.USER_ID;
import static com.to8to.thrift.diary.behavior.ListBehaviorRequest._Fields._ID;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.thrift.meta_data.FieldMetaData;
import org.apache.thrift.protocol.TType;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.to8to.commons.utils.StringUtil;
import com.to8to.commons.utils.ThriftUtil;
import com.to8to.thrift.diary.advanced.ListJingXuanSceneRequest;
import com.to8to.thrift.diary.advanced.ListNewestSceneRequest;
import com.to8to.thrift.diary.advanced.ListSceneDiaryViewsRequest;
import com.to8to.thrift.diary.advanced.RecommendSceneRequest;
import com.to8to.thrift.diary.advanced.VerifyRequest;
import com.to8to.thrift.diary.behavior.BehaveRequest;
import com.to8to.thrift.diary.behavior.ListBehaviorRequest;
import com.to8to.thrift.diary.comment.CreateCommentRequest;
import com.to8to.thrift.diary.consts.constConstants;
import com.to8to.thrift.diary.diary.CreateDiaryRequest;
import com.to8to.thrift.diary.module.TBehavior;
import com.to8to.thrift.diary.module.TComment;
import com.to8to.thrift.diary.module.TDiary;
import com.to8to.thrift.diary.module.TProduct;
import com.to8to.thrift.diary.module.TScene;
import com.to8to.thrift.diary.module.TUserScore;
import com.to8to.thrift.diary.product.CreateProductRequest;
import com.to8to.thrift.diary.scene.CreateSceneRequest;
import com.to8to.thrift.diary.stconfigs.GetStConfigSubIdMapRequest;
import com.to8to.thrift.diary.user.UpdateUserRequest;

/**
 * 验证输入的数据
 * 
 * @author Ervin.zhang
 */
public class Validator
{
    /**
     * 验证现场请求的数据
     * 
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validSceneReq(CreateSceneRequest req)
    {
        if (req == null || req.getScene() == null)
        {
            return "error : null scene";
        }

        return validScene(req.getScene());
    }

    public static String validScene(TScene scene)
    {
        // owner_id 和 com_id不能同时为空
        if (StringUtil.isEmpty(scene.getOwner_id()) && scene.getCom_id() <= 0)
        {
            return "error : owner_id or com_id must be setted!";
        }

        // 理论上name_u 和 name_c不能同时为空
        // 但APP在创建现场时的确没有name_u，与强哥沟通过，确认create时name的规则如下:
        // owner_id 为空的时候name_c不能为空
        // owner_id 不为空的时候name_c和name_u可以为空
        if (StringUtil.isEmpty(scene.getOwner_id()) && StringUtil.isEmpty(scene.getName_c()))
        {
            return "error : name_c must be setted when owner_id is empty!";
        }
        if (scene.getPlatform() <= 0)
        {
            return notPositive("platform");
        }
        if (scene.getPublish_source() <= 0)
        {
            return notPositive("publish_source");
        }
        return null;
    }

    public static BasicDBObject validateSceneFilter(BasicDBObject parsed)
    {
        BasicDBObject query = new BasicDBObject();
        if (parsed == null)
        {
            return query;
        }
        for (String key : parsed.keySet())
        {
            Object value = parsed.get(key);
            if (value instanceof String || value instanceof Number)
            {
                TScene._Fields fields = TScene._Fields.findByName(key);
                if (fields != null)
                {
                    FieldMetaData fieldMeta = TScene.metaDataMap.get(fields);
                    if (fieldMeta != null)
                    {
                        byte vtype = fieldMeta.valueMetaData.type;
                        if (vtype == TType.STRING && value instanceof Number)
                            query.put(key, String.valueOf(value));
                        else if (vtype == TType.I32 && value instanceof String && StringUtil.isNumeric((String) value))
                            query.put(key, Integer.parseInt((String) value));
                        else if (vtype == TType.I64 && value instanceof String && StringUtil.isNumeric((String) value))
                            query.put(key, Long.parseLong((String) value));
                        else if (vtype == TType.DOUBLE && value instanceof String && StringUtil.isNumeric((String) value))
                            query.put(key, Double.parseDouble((String) value));
                        else
                            query.put(key, value);

                        continue;
                    }
                }
            }

            query.put(key, value);
        }
        return query;
    }

    /**
     * 验证创建日志的请求
     * 
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validDiaryReq(CreateDiaryRequest req)
    {
        if (req == null || req.getDiary() == null)
        {
            return "error : null diary";
        }
        return validDiary(req.getDiary());
    }

    public static String validDiary(TDiary diary)
    {
        TScene scene = ThriftUtil.dbObject2ThriftObject(Commons.mongo.findById(Tables.Scene, diary.getScene_id()), TScene.class);

        if (null == scene)
        {
            return notValidated("scene_id");
        }

        if (diary.getJianli_id() == 0 && StringUtil.isEmpty(diary.getOwner_id()))
        {
            return emptyField("owner_id");
        }
        //        if ((!StringUtil.isEmpty(scene.getOwner_id()) && !scene.getOwner_id().equals(diary.getOwner_id())))
        //        {
        //            return notValidated("owner_id");
        //        }

        if (StringUtil.isEmpty(diary.getScene_id()))
        {
            return emptyField("scene_id");
        }
        if (diary.getProgress_id() <= 0)
        {
            return emptyField("progress_id");
        }
        if (diary.getTag_id() <= 0)
        {
            return emptyField("tag_id");
        }
        if (diary.getPlatform() <= 0)
        {
            return notPositive("platform");
        }
        if (diary.getPublish_source() <= 0)
        {
            return notPositive("publish_source");
        }
        else if (diary.getPublish_source() == 1)
        {
            if (!StringUtil.equals(diary.getOwner_id(), scene.getOwner_id()))
            {
                return notValidated("owner_id");
            }
        }
        return null;
    }

    /**
     * 验证创建商品的请求
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validProductReq(CreateProductRequest req)
    {
        if (req == null || req.getProduct() == null)
            return "error : null product";
        return validProduct(req.getProduct());
    }

    /**
     * 校验商品参数是否合法 
     */
    public static String validProduct(TProduct product)
    {
        if ((product.getUnit_price() <= 0) && (product.getTotal_price() <= 0))
            return notPositive("price");
        if (StringUtil.isEmpty(product.getName()))
            return emptyField("name");
        if (StringUtil.isEmpty(product.getScene_id()))
            return emptyField("scene_id");
        if (product.getPlatform() <= 0)
            return notPositive("platform");
        if (product.getPublish_source() <= 0)
            return notPositive("publish_source");
        if (product.getCategory_1() <= 0)
            return notPositive("category1");
        if (product.getCategory_2() <= 0)
            return notPositive("category2");
        if (!Arrays.asList(new Integer[] { 1, 2, 3 }).contains(product.getFeeling()))
            return notPositive("feeling");
        return null;
    }

    /**
     * 验证创建评论的请求
     * 
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validCommentReq(CreateCommentRequest req)
    {
        if (req == null || req.getComment() == null)
        {
            return "error : null comment";
        }
        return validComment(req.getComment());
    }

    public static String validComment(TComment comment)
    {
        if (StringUtil.isEmpty(comment.getScene_id()))
        {
            return emptyField("scene_id");
        }
        if (StringUtil.isEmpty(comment.getOwner_id()))
        {
            return emptyField("owner_id");
        }
        if (StringUtil.isEmpty(comment.getContent()))
        {
            return emptyField("content");
        }
        if (StringUtil.isEmpty(comment.getUser_id()))
        {
            return emptyField("user_id");
        }
        if (comment.getTgt_type() <= 0)
        {
            return notPositive("tgt_type");
        }
        if (comment.getPlatform() <= 0)
        {
            return notPositive("platform");
        }
        if (comment.getPublish_source() <= 0)
        {
            return notPositive("publish_source");
        }

        if (comment.getTgt_type() == constConstants.TARGET_TYPE_DIARY)
        {
            if (StringUtil.isEmpty(comment.getDiary_id()))
            {
                return emptyField("diary_id");
            }
            else
            {
                DBObject diary_db = Commons.mongo.findById(Tables.Diary, comment.getDiary_id());
                if (diary_db == null)
                    return "diary id error!";
                TDiary diary = ThriftUtil.dbObject2ThriftObject(diary_db, TDiary.class);
                if (!diary.getScene_id().equals(comment.getScene_id()))
                {
                    //日记所属现场scene_id不对
                    return "scene id error!";
                }
            }
        }
        else if (comment.getTgt_type() == constConstants.TARGET_TYPE_PRODUCT)
        {
            //现在不能对单个商品进行评论，所以对清单的评论不能判断这个product_id，先暂时屏蔽掉
            /*if(StringUtil.isEmpty(comment.getProduct_id())){
                return emptyField("product_id");
            }else{
                DBObject product_db = Commons.mongo.findById(Tables.Product, comment.getProduct_id());
                TProduct product = ThriftUtil.dbObject2ThriftObject(product_db, TProduct.class);
                if(!product.getScene_id().equals(comment.getScene_id())){
                    //商品所属现场scene_id不对
                    return "scene id error!";
                }
            }*/
        }
        else if (comment.getTgt_type() == constConstants.TARGET_TYPE_COMMENT)
        {
            if (StringUtil.isEmpty(comment.getParent_comment_id()))
            {
                return emptyField("parent comment id");
            }

            if (StringUtil.isEmpty(comment.getParent_comment_user_id()))
            {
                return emptyField("parent comment user id");
            }

            if (StringUtil.isEmpty(comment.getRef_comment_user_id()))
            {
                return emptyField("ref comment user id");
            }

            if (StringUtil.isEmpty(comment.getRef_comment_id()))
            {
                return emptyField("ref_comment_id");
            }
            else
            {
                DBObject ref_comment_db = Commons.mongo.findById(Tables.Comment, comment.getRef_comment_id());

                if (ref_comment_db == null)
                    return "ref comment id error!";

                TComment ref_comment = ThriftUtil.dbObject2ThriftObject(ref_comment_db, TComment.class);

                if (!ref_comment.getScene_id().equals(comment.getScene_id()))//被评论所属现场scene_id不对
                    return "scene id error!";
            }
        }
        return null;
    }

    /**
     * 验证ListNewestScene方法的参数
     * 
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validListNewestScene(ListNewestSceneRequest req)
    {
        if (req == null)
        {
            return "null request!";
        }
        if (req.getOffset() < 0)
        {
            return "negative 'offset'!";
        }
        if (req.getLimit() <= 0)
        {
            return notPositive("limit");
        }
        if (req.getCond() != null)
        {
            if (req.getCond().getFields() == null || req.getCond().getFields().isEmpty())
            {
                return emptyField("cond.fields");
            }
        }
        return null;
    }

    /**
     * 验证ListNewestScene方法的参数
     * 
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validListJingXuanScene(ListJingXuanSceneRequest req)
    {
        if (req == null)
            return "null request!";

        if (req.getOffset() < 0 || req.getLimit() <= 0)
            return "negative 'offset' or 'limit'!";

        if (req.getCond() != null)
        {
            if (req.getCond().getFields() == null || req.getCond().getFields().isEmpty())
            {
                return emptyField("cond.fields");
            }
        }
        return null;
    }

    /**
     * 验证ListSceneDiaryViews方法的参数
     * 
     * @return 如果验证失败，返回失败信息，否则返回null
     */
    public static String validListSceneDiaryViews(ListSceneDiaryViewsRequest req)
    {
        if (req == null)
            return "null request!";

        if (req.getOffset() < 0 || req.getLimit() <= 0)
            return "negative 'offset' or 'limit'!";

        if (req.getCond() != null)
        {
            if (req.getCond().getFields() == null || req.getCond().getFields().isEmpty())
            {
                return emptyField("cond.fields");
            }
        }
        return null;
    }

    public static String validBehave(TBehavior behavior)
    {
        if (StringUtil.isEmpty(behavior.getTgt_id()))
        {
            return emptyField("tgt_id");
        }
        if (StringUtil.isEmpty(behavior.getUser_id()) && (behavior.getBhv_type() != constConstants.BEHAVIOR_TYPE_VIEW))
        {
            return emptyField("user_id");
        }
        if (behavior.getBhv_type() <= 0)
        {
            return "error : please set behavior type!";
        }
        if (behavior.getTgt_type() <= 0)
        {
            return "error : please set target type!";
        }
        if (behavior.getStatus() != 1 && behavior.getStatus() != -1)
        {
            return "error : invalid behavior status!";
        }
        // 只能收藏现场
        if (behavior.getBhv_type() == constConstants.BEHAVIOR_TYPE_COLL && behavior.getTgt_type() != constConstants.TARGET_TYPE_SCENE)
        {
            return "error : only scene can be collectted";
        }
        if (behavior.getBhv_type() == constConstants.BEHAVIOR_TYPE_VIEW && behavior.getStatus() == -1)
        {
            return "error : can't cancel view event";
        }
        if (behavior.getBhv_type() == constConstants.BEHAVIOR_TYPE_LIKE && behavior.getTgt_type() != constConstants.TARGET_TYPE_DIARY)
        {
            return "error : only can like diary!";
        }
        return null;
    }

    public static String validBehaveReq(BehaveRequest req)
    {
        if (req == null || req.getBehaviors() == null)
        {
            return "error : null behavior request";
        }
        for (TBehavior behavior : req.getBehaviors())
        {
            String res = validBehave(behavior);
            if (!StringUtil.isEmpty(res))
            {
                return res;
            }
        }
        return null;
    }

    public static String validListBehaviorRequest(ListBehaviorRequest req)
    {

        if (req == null)
        {
            return "error : null request";
        }
        if (req.getFields() == null || req.getFields().size() == 0)
        {
            return "error : please set the fields!";
        }
        List<String> validFields =
            Arrays.asList(_ID.getFieldName(), USER_ID.getFieldName(), TGT_ID.getFieldName(), BHV_TYPE.getFieldName(), TGT_TYPE.getFieldName(), STATUS.getFieldName());
        for (String field : req.getFields())
        {
            if (!validFields.contains(field))
            {
                return "error : " + field + " is not exsits";
            }
        }
        return null;
    }

    public static String validListUpdateUserRequest(UpdateUserRequest req)
    {

        if (req == null)
        {
            return "error : null request";
        }
        if (StringUtil.isEmpty(req.get_id()))
        {
            return "error : no user_id";
        }

        List<String> valid_field_list = new ArrayList<String>();
        valid_field_list.add(TUserScore._Fields.PROGRESS_ID.getFieldName());
        valid_field_list.add(TUserScore._Fields.PROGRESS_NOTICE.getFieldName());
        valid_field_list.add(TUserScore._Fields.PROGRESS_STIME.getFieldName());

        List<String> this_field_list = new ArrayList(req.getFields());
        this_field_list.removeAll(valid_field_list);

        if (this_field_list.size() > 0)
        {
            return "error : please set the progress!";
        }
        else
        {
            return null;
        }
    }

    public static String validRecommendSceneRequest(RecommendSceneRequest req)
    {
        if (req == null)
        {
            return "error : null request";
        }
        if (req.getArea() < 0)
        {
            return "error : negative area!";
        }
        if (req.getHouse_type() < 0)
        {
            return "error : negative house type!";
        }
        if (req.getLimit() <= 0)
        {
            return notPositive("limit");
        }
        return null;
    }

    public static String validVerifyRequest(VerifyRequest req)
    {
        if (req == null)
        {
            return "error : null request";
        }
        if (StringUtil.isEmpty(req.getEntity_id()))
        {
            return emptyField("enity_id");
        }
        if (req.getEntity_type() <= 0)
        {
            return notPositive("entity_type");
        }

        //        req.getEntity_id();
        //        switch (req.getEntity_type())
        //        {
        //        case constConstants.TARGET_TYPE_SCENE:
        //        {
        //            break;
        //        }
        //        case constConstants.TARGET_TYPE_DIARY:
        //        {
        //            break;
        //        }
        //        case constConstants.TARGET_TYPE_PRODUCT:
        //        {
        //            break;
        //        }
        //        case constConstants.TARGET_TYPE_COMMENT:
        //        {
        //            break;
        //        }
        //        }

        return null;
    }

    public static String validGetStConfigSubIdMapRequest(GetStConfigSubIdMapRequest req)
    {
        if (req == null)
        {
            return "error : null request";
        }
        if (StringUtil.isEmpty(req.getType_name()))
        {
            return emptyField("type_name");
        }
        if (req.getLevel() > 1)
        {
            if (StringUtil.isEmpty(req.getParent_id()))
            {
                return notPositive("parent_id");
            }
        }
        return null;
    }

    public static String notValidated(String field)
    {
        return "error : " + field + " must be a validated value!";
    }

    public static String notPositive(String field)
    {
        return "error : " + field + " must be a positive integer number!";
    }

    public static String emptyField(String field)
    {
        return "error : " + field + " is empty!";
    }

}
